package com.own.business.exam.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.own.business.exam.business.service.ExamPaperService;
import com.own.business.exam.business.service.ExamRuleAccountService;
import com.own.business.exam.business.service.ExamRulePaperService;
import com.own.business.exam.business.service.ExamRuleQuestionCountService;
import com.own.business.exam.business.service.ExamRuleQuestionService;
import com.own.business.exam.business.service.ExamRuleService;
import com.own.business.exam.business.service.ExamService;
import com.own.business.exam.common.exception.ExamException;
import com.own.business.exam.entity.bo.ExamRuleBo;
import com.own.business.exam.entity.map.ExamRuleMapVo;
import com.own.business.exam.entity.po.ExamPaper;
import com.own.business.exam.entity.po.ExamRule;
import com.own.business.exam.entity.po.ExamRuleAccount;
import com.own.business.exam.entity.po.ExamRulePaper;
import com.own.business.exam.entity.po.ExamRuleQuestion;
import com.own.business.exam.entity.query.ExamQuery;
import com.own.business.exam.entity.query.ExamRuleQuery;
import com.own.business.exam.entity.vo.ExamRuleVo;
import com.own.business.exam.entity.vo.ExamVo;
import com.own.business.exam.mapper.ExamRuleMapper;
import com.own.component.common.base.service.impl.AbstractBaseService;
import com.own.component.common.model.UpdateModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * ExamRuleServiceImpl
 * <p>
 * 一个用户由于考试规则的多样性，可能会存在多份规则的情况，系统会选择就近的规则进行匹配
 *
 * @author 陈学礼 （你是一段成熟的代码，要学会自己改bug）
 * @version 4.0.0
 * @date 2021/05/18 14:43:47
 * @since 4.0.0
 */
@Slf4j
@Service
public class ExamRuleServiceImpl extends AbstractBaseService<
        ExamRule,
        ExamRuleBo,
        ExamRuleVo,
        ExamRuleMapVo,
        ExamRuleQuery,
        ExamRuleMapper
        > implements ExamRuleService {

    @Resource
    private ExamService examService;
    @Resource
    private ExamPaperService examPaperService;
    @Resource
    private ExamRuleAccountService examRuleAccountService;
    @Resource
    private ExamRulePaperService examRulePaperService;
    @Resource
    private ExamRuleQuestionService examRuleQuestionService;
    @Resource
    private ExamRuleQuestionCountService examRuleQuestionCountService;

    /**
     * 获取查询条件
     *
     * @param query 查询条件
     * @return 查询条件对象
     */
    @Override
    public LambdaQueryWrapper<ExamRule> lambdaQueryWrapper(ExamRuleQuery query) {
        boolean keywordsFlag = StringUtils.isNotEmpty(query.getKeywords());
        // 所有的考试id
        var examIdList = keywordsFlag
                ? examService.all(new ExamQuery().setTitle(query.getKeywords())).stream().map(ExamVo::getId).collect(Collectors.toList())
                : new ArrayList<String>();
        return super.lambdaQueryWrapper(query)
                .and(StringUtils.isNotEmpty(query.getKeywords()), i -> i
                        .like(ExamRule::getName, query.getName())
                        .or(examIdList.size() > 0)
                        .in(examIdList.size() > 0, ExamRule::getFkExamId, examIdList)
                )
                .eq(query.getExamId() != null, ExamRule::getFkExamId, query.getExamId())
                .like(StringUtils.isNotEmpty(query.getName()), ExamRule::getName, query.getName())
                .eq(query.getType() != null, ExamRule::getType, query.getType())
                .eq(query.getIsAssignAccount() != null, ExamRule::getIsAssignAccount, query.getIsAssignAccount())
                .eq(query.getIsAssignNumber() != null, ExamRule::getIsAssignNumber, query.getIsAssignNumber())
                .orderByDesc(ExamRule::getGmtCreate);
    }

    /**
     * 查询所有的数据
     *
     * @param query 查询条件
     * @return 所有的列表数据
     */
    @Override
    public List<ExamRuleVo> all(ExamRuleQuery query) {
        return listByWrapper(lambdaQueryWrapper(query)).stream().map(ExamRuleVo::new).collect(Collectors.toList());
    }

    /**
     * 添加信息
     *
     * @param bo 添加对象
     * @return 添加标识
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UpdateModel<ExamRuleVo> add(ExamRuleBo bo) {
        var updateModel = super.add(bo);
        var vo = updateModel.getData();
        if (bo.getIsAssignAccount() == 1) {
            // 添加账号信息
            if (bo.getAccountList().size() == 0) {
                throw new ExamException("当前规则为指定账号类型，检测到允许的账号列表为空，请添加账号信息");
            }
            // todo
//            examRuleAccountService.bindBatch(vo.getId(), bo.getAccountList());
        }
        if (bo.getCountList() != null && bo.getCountList().size() > 0) {
            bo.getCountList().forEach(item -> item.setRuleId(vo.getId()));
            examRuleQuestionCountService.addBatch(bo.getCountList());
        }
        return updateModel;
    }

    /**
     * 修改信息
     *
     * @param pk 主键id
     * @param bo 修改对象
     * @return 修改标识
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UpdateModel<ExamRuleVo> update(Long pk, ExamRuleBo bo) {
        return super.update(pk, bo);
    }

    /**
     * 删除信息
     *
     * @param pk 主键id
     * @return 删除标识
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UpdateModel<Boolean> delete(Long pk) {
        return new UpdateModel<>().check(
                examPaperService.delete(ExamPaper::getFkRuleId, pk),
                examRuleAccountService.delete(ExamRuleAccount::getFkRuleId, pk),
                examRulePaperService.delete(ExamRulePaper::getFkRuleId, pk),
                examRuleQuestionService.delete(ExamRuleQuestion::getFkRuleId, pk),
                super.delete(pk)
        );
    }
}
